<?php

namespace App\Kuafu\Order\Service;

use App\Exceptions\BaseException;
use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\CouponExt\Enum\CouponExtEnum;
use App\Kuafu\CouponExt\Exceptions\CouponExtException;
use App\Kuafu\CustomerCoupon\Service\CustomerCouponService;
use App\Kuafu\Order\Enum\CodeEnum;
use App\Kuafu\Order\Enum\OrderInfoEnum;
use App\Kuafu\Order\Exceptions\OrderWaringException;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;

class OrderPlacingService extends BaseService
{

    /**
     * 通过券码核销生成对应订单
     *
     * @param int $couponType
     * @param string $couponCode
     * @param int $couponNum
     * @param bool $isPrint
     * @return array
     * @throws BaseException
     * @throws CouponExtException
     * @throws GuzzleException
     * @throws OrderWaringException
     */
    public function genOrderByCheckCoupon(int $couponType, string $couponCode, int $couponNum, bool $isPrint): array
    {

        OrderLockService::lockOrderScan($this->shopId, $couponCode, OrderLockService::LOCK_METHOD_TYPE_MERCHANT_COUPON);

        // 查询券信息,获取关联三方 ID
        $couponInfo = CustomerCouponService::getAllTypeCouponWithVerify($this->shopId, $couponCode, $couponType);

        // 判断是否是夸父券
        if ($couponType == CouponExtEnum::EXT_PLATFORM_KUAFU) {
            // TODO 老的核销流程
            CustomerCouponService::use($couponCode, $this->shopId);
            return self::returnData(BaseCodeEnum::OK, '核销成功');
        }

        try {
            // 校验是否是单张券
            if (!is_numeric($couponInfo['canUseProduct'])) {
                return BaseService::returnData(1, '暂不支持多选券或其他代金券');
            }

            $couponInfo['canUseProduct'] = (int)$couponInfo['canUseProduct'];

            $data = self::genPostDataByCouponInfo($couponInfo, $couponNum);

            $order = new OrderHandleService($this->brandId, $this->shopId);

            // 计价
            $order->checkCouponCalcPrice($data);
            // 校验金额是否相同up
            $order->handleOrder($data);

            // 核销三方优惠券
            if (!empty($order->getOrderCalc()->getNeedCheckExtCoupon())) {
                // 核销优惠券
                foreach ($order->getOrderCalc()->getNeedCheckExtCoupon() as $coupon) {
                    $couponType = $coupon['type'] ?? OrderInfoEnum::POS_ORDER_PAYMENT_COUPON_MEITUAN;
                    $couponExt  = new OrderCouponExternalService(1, $this->shopId, $this->brandId,
                        $order->getOrderId(true));
                    $couponExt->resetCouponExtPlatformByPosPayment($couponType);
                    $couponExt->consumeCouponExt($coupon['code'], $coupon['num'], (int)$coupon['couponDiscountPrice']);
                }
            }

            $orderResult                  = $order->getOrderInfo(true)->toArray();
            $orderResult['extCouponList'] = $order->getOrderExtCoupon(true);

            if (empty($orderResult['extCouponList'])) {
                return BaseService::returnData(1, '核销失败:');
            }

            $orderPay = new OrderPay($this->brandId, $this->shopId, $orderResult['orderId']);
            $orderPay->setIsSendMQ($isPrint);
            $orderPay->cashPay();
            $orderPay->successV2();
            $orderPay->finish();

            // 写入核销记录表
            CustomerCouponService::verifyCode($orderResult);

            return BaseService::returnData(BaseCodeEnum::OK, '核销成功', [
                'orderId'   => (string)$orderResult['orderId'],
                'serialNum' => $orderResult['serialNum'],
            ]);

        } catch (\Exception $exception) {
            Log::channel('order')->error('OrderPlacingService_orderError_genOrderByCheckCoupon', [
                'postData' => $data,
                'errMsg'   => $exception->getMessage(),
                'line'     => $exception->getLine(),
                'file'     => $exception->getFile(),
            ]);

            return BaseService::returnData(1, '核销失败:' . $exception->getMessage());
        } finally {
            OrderLockService::releaseOrderScan($this->shopId, $couponCode,
                OrderLockService::LOCK_METHOD_TYPE_MERCHANT_COUPON);
        }
    }


    private function genPostDataByCouponInfo($couponInfo, $quantity): array
    {
        $data = [
            'sourceType' => CodeEnum::SOURCE_TYPE_MERCHANT_CHECK_COUPON,
            'detail'     => [
                [
                    'productId' => $couponInfo['canUseProduct'],
                    'num'       => $quantity,
                ]
            ],
            'extCoupon'  => [
                [
                    "code"    => $couponInfo['couponCode'],
                    "codeUrl" => $couponInfo['couponCode'],
                    "num"     => $quantity,
                    "type"    => CouponExtEnum::switchExtPlatform2OrderPayment($couponInfo['couponFrom'])
                ]
            ],
            'remark'     => '',
        ];

        return OrderService::getOrderFormatPostData($data);

    }
}
